/* UniApoLib
 * filename:  SDSFile.h
 * date:      June 2010
 * author:    Jeffrey Geyssens
 * about:     This file contains implementation of the SDS File Class.
 *            It is used created and modified by the SDSEditor.
 *
 *
 * Marked as incompleted*: 25th june 2010 and no changes since
 * TO-DO: implement STDPLUGS plugin system
 * TO-DO: check entryNo boundries
 */

#ifndef _SDSFILE_H
#define	_SDSFILE_H
#include "UniApoFile.h"
#include "Section.h"
#include "StaticDataEntry.h"
#include "DynamicDataHeading.h"
#include "DynamicDataEntry.h"
#include "string"
#include <stdlib.h>

using namespace std;

class SDSFile : public UniApoFile {
public:
    SDSFile();
    SDSFile(const SDSFile& orig);
    virtual ~SDSFile();
    //Operations for Static Data
    void addStatic(string a, string v, string st, string sa);
    void modifyStatic(string a, string v, string st, string sa, int entryNo);
    void removeStatic(int entryNo);
    void printStatic();

    //Operations using Dynamic Data Header
    void addHeading(string a, string st, string sa);
    void addHeading(int col, string a, string st, string sa);
    void modifyHeading(int col, string a, string st, string sa);
    void removeHeading(int entryNo);
    void printHeader();
    int getDScomponent();

    //Operations on Entry Base
    void createNewEntry();
    void addEntryComponent(string compdata, int comp);
    void clearEntryComponent(int comp);
    void printTemp();


    //Operation using Dynamic Data Section
    //Typical entry value is ommited because of the tempdata variable use.
    void addEntry();
    void addEntry(int entryNo);
    void modifyEntry(int entryNo);
    void removeEntry(int entryNo);
    void printEntries();
    vector<DynamicDataEntry>& getContent();
    string getDataString(int entryNo);



    //Standard File operations
    void name(string n);
    void print();
    void buildFile();
    void loadFile();

private:
    Section<StaticDataEntry> static_data;
    Section<DynamicDataHeading> dynamic_data_header;
    Section<DynamicDataEntry> dynamic_data;
    int datastringcomponent;
    DynamicDataEntry tempdata;

};

SDSFile::SDSFile() {

    datastringcomponent = -1;
    static_data.setHeader(".STATIC");
    static_data.setFooter(".END_STATIC");
    dynamic_data_header.setHeader(".DYNAMIC_HEADER");
    dynamic_data_header.setFooter(".END_DYNAMIC_HEADER");
    dynamic_data.setHeader(".DYNAMIC");
    dynamic_data.setFooter(".END_DYNAMIC");

}

SDSFile::SDSFile(const SDSFile& orig) {
    filename = orig.filename;
    extension = orig.extension;
    path = orig.path;
    scriptpath = orig.path;
    datastringcomponent = orig.datastringcomponent;
    static_data = orig.static_data;
    dynamic_data_header = orig.dynamic_data_header;
    dynamic_data = orig.dynamic_data;
}

SDSFile::~SDSFile() {
}

void SDSFile::addStatic(string a, string v, string st, string sa) {
    StaticDataEntry sde;
    sde.setAttribName(a);
    sde.setVal(v);
    sde.setSourceT(st);
    sde.setSourceA(sa);
    static_data.add(sde);
}

void SDSFile::modifyStatic(string a, string v, string st, string sa,
        int entryNo) {
    StaticDataEntry sde;
    sde.setAttribName(a);
    sde.setVal(v);
    sde.setSourceT(st);
    sde.setSourceA(sa);
    static_data.modify(sde, entryNo);
}

void SDSFile::removeStatic(int entryNo) {
    static_data.remove(entryNo);
}

void SDSFile::printStatic() {
    static_data.print();
}

void SDSFile::addHeading(string a, string st, string sa) {
    DynamicDataHeading ddh;
    int componentnumber;
    componentnumber = dynamic_data_header.getSize() + 1;
    cout << "xx: " << componentnumber;
    ddh.setComponent(componentnumber);
    ddh.setAttribName(a);
    if (a == "@DS@") {
        datastringcomponent = componentnumber;
    } else {
        ddh.setSourceT(st);
        ddh.setSourceA(sa);
    }
    dynamic_data_header.add(ddh);
}

void SDSFile::addHeading(int c, string a, string st, string sa) {
    DynamicDataHeading ddh;
    ddh.setComponent(c);
    ddh.setAttribName(a);
    if (a == "@DS@") {
        datastringcomponent = c;
    } else {
        ddh.setSourceT(st);
        ddh.setSourceA(sa);
    }

    dynamic_data_header.add(ddh);

}

void SDSFile::modifyHeading(int c, string a, string st, string sa) {
    DynamicDataHeading ddh;
    ddh.setComponent(c);
    ddh.setAttribName(a);
    if (a == "@DS@") {
        datastringcomponent = c;
    } else {
        ddh.setSourceT(st);
        ddh.setSourceA(sa);
    }
    dynamic_data_header.modify(ddh, c);
}

void SDSFile::removeHeading(int entryNo) {
    dynamic_data_header.remove(entryNo);
    //do something if data-string
}

void SDSFile::printHeader() {
    dynamic_data_header.print();
}

int SDSFile::getDScomponent() {
    return datastringcomponent;
}

void SDSFile::createNewEntry() {
    DynamicDataEntry blank;
    for (int i = 0; i < dynamic_data_header.getSize(); i++) {
        blank.addContent("@VOID@");
    }
    tempdata = blank;

}

void SDSFile::addEntryComponent(string compdata, int comp) {
    tempdata.modifyContent(compdata, comp);
}

void SDSFile::clearEntryComponent(int comp) {
    tempdata.modifyContent("@VOID@", comp);
}

void SDSFile::printTemp() {
    cout << tempdata << endl;
}

void SDSFile::addEntry() {
    string checkDS;

    checkDS = tempdata.getContent(datastringcomponent);

    if (checkDS != "@VOID@") {
        dynamic_data.add(tempdata);
    } else {
        cerr << "ERROR (SDSFile):" << endl;
        cerr << "No data string present" << endl;
    }
}

void SDSFile::addEntry(int entryNo) {
    string checkDS;
    checkDS = tempdata.getContent(datastringcomponent);
    if (checkDS != "@VOID@") {
        dynamic_data.insert(tempdata, entryNo);
    } else {
        cerr << "ERROR (SDSFile):" << endl;
        cerr << "No data string present" << endl;
    }

}

void SDSFile::modifyEntry(int entryNo) {
    string checkDS;
    checkDS = tempdata.getContent(datastringcomponent);
    if (checkDS != "@VOID@") {
        dynamic_data.modify(tempdata, entryNo);
    } else {
        cerr << "ERROR (SDSFile):" << endl;
        cerr << "No data string present" << endl;
    }


}

void SDSFile::removeEntry(int entryNo) {
    dynamic_data.remove(entryNo);
}

void SDSFile::printEntries() {
    dynamic_data.print();
}

vector<DynamicDataEntry>& SDSFile::getContent() {
    vector<DynamicDataEntry>& ret = dynamic_data.getSectionData();

    return ret;
}
//Usual File related procedures

void SDSFile::name(string n) {
    filename = n;
    extension = "SDS";
    this->setPath();
}

void SDSFile::print() {
    static_data.print();
    dynamic_data_header.print();
    dynamic_data.print();

}

void SDSFile::buildFile() {
    ofstream newSDSFile;
    newSDSFile.open(path.c_str());
    newSDSFile << "filename: " << filename.c_str() << "\n";
    newSDSFile << "extension: " << extension.c_str() << "\n \n";
    newSDSFile.close();
    static_data.buildFile(path);
    dynamic_data_header.buildFile(path);
    dynamic_data.buildFile(path);
}

void SDSFile::loadFile() {
    ifstream SDSFile(path.c_str());
    string line;
    string start_static;
    string start_dhead;
    string start_d;


    //Get Symdef Section
    if (SDSFile.is_open()) {
        getline(SDSFile, line);
        line = line.substr(9, line.size());
        if (line[0] == ' ') {
            line.erase(0, 1);
        }
        this->name(line);

        while (line != ".STATIC") {
            getline(SDSFile, line);
        }

        while (line != ".END_STATIC") {
            start_static = "attribute_name:";
            getline(SDSFile, line);

            if (line.find(start_static) != line.npos) {

                StaticDataEntry s;
                line = line.substr(16, line.size());
                s.setAttribName(line);
                getline(SDSFile, line);
                line = line.substr(7, line.size());
                s.setVal(line);
                getline(SDSFile, line);
                line = line.substr(14, line.size());
                s.setSourceT(line);
                getline(SDSFile, line);
                line = line.substr(18, line.size());
                s.setSourceA(line);
                static_data.add(s);


            }
        }

        getline(SDSFile, line);
        while (line != ".DYNAMIC_HEADER") {
            getline(SDSFile, line);
        }

        while (line != ".END_DYNAMIC_HEADER") {
            start_dhead = "component:";
            getline(SDSFile, line);

            if (line.find(start_dhead) != line.npos) {

                //DynamicDataHeading h;
                line = line.substr(11, line.size());
                int i;
                stringstream ss(line);
                string a, st, sa;
                ss >> i;
                //h.setComponent(i);
                getline(SDSFile, line);
                line = line.substr(16, line.size());

                //h.setAttribName(line);
                a = line;
                getline(SDSFile, line);
                line = line.substr(14, line.size());
                st = line;
                //h.setSourceT(line);
                getline(SDSFile, line);
                line = line.substr(18, line.size());
                //h.setSourceA(line);
                sa = line;
                this->addHeading(i, a, st, sa);

            }
        }
        getline(SDSFile, line);
        while (line != ".DYNAMIC") {
            getline(SDSFile, line);
        }

        while (line != ".END_DYNAMIC") {
            getline(SDSFile, line);
            int i, part;
            string entry, xline;
            i = 1;
            this->createNewEntry();
            if (line.find("(") != line.npos) {

                xline = line.substr(1, line.size());
                while (xline.find(";") != line.npos) {
                    part = int(xline.find(";"));
                    entry = xline.substr(0, part);

                    this->addEntryComponent(entry, i);
                    xline = xline.substr(entry.size() + 1, xline.size());
                    i++;
                }
                this->addEntry();

            }
        }
    }
}

string SDSFile::getDataString(int entryNo){
    if (datastringcomponent != -1){
        DynamicDataEntry dde = dynamic_data.get(entryNo);
        return dde.getContent(datastringcomponent);
    };
    return "N/A";


}
#endif	/* _SDSFILE_H */

